package testview.zhen.com.myapplication.design.consumer_producer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Create by ldr
 * on 2019/8/23 17:46.
 * 如果不能将并发与容量控制都封装在缓冲区中，就只能由消费者与生产者完成。最简单的方案是使用朴素的wait && notify机制。
 */
public class WaitNotifyModel implements Model {
    private final Object BUFFER_LOCK = new Object();
    private final Queue<Task> buffer = new LinkedList<>();
    private final int mCap;

    private final AtomicInteger increTaskNo = new AtomicInteger(0);

    public WaitNotifyModel(int cap){
        this.mCap = cap;
    }

    @Override
    public Runnable newRunnableConsumer() {
        return new ConsumerImpl();
    }

    @Override
    public Runnable newRunnableProducer() {
        return new ProducerImpl();
    }

    private class ConsumerImpl extends AbstractConsumer implements Consumer,Runnable{

        @Override
        public void consume() throws InterruptedException {
            synchronized (BUFFER_LOCK){
                while (buffer.size()==0){
                    BUFFER_LOCK.wait();
                }
                Task task = buffer.poll();
                assert  task != null;
                // 固定时间范围的消费，模拟相对稳定的服务器处理过程
                Thread.sleep(500 + (long) (Math.random() * 500));
                System.out.println("consume: " + task.no);
                BUFFER_LOCK.notifyAll();
            }
        }
    }

    private class ProducerImpl extends AbstractProducer implements Producer,Runnable{

        @Override
        public void proudce() throws InterruptedException {
            //不定期生产，模拟随机用户请求
            Thread.sleep((long) (Math.random() * 1000));
            synchronized (BUFFER_LOCK){
                while (buffer.size() == mCap){
                    BUFFER_LOCK.wait();
                }
                Task task = new Task(increTaskNo.getAndIncrement());
                buffer.offer(task);
                System.out.println("produce:"+task.no);
                BUFFER_LOCK.notifyAll();
            }
        }
    }



}
